﻿using HpApi.Diagnostics;
using HpApi.Types;
using Network.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.Data.Json;
using Windows.Foundation.Collections;
using Windows.Web.Http;

namespace HpApi
{
    public class HpApi
    {
        public static Action<string> HpApIResponse;
        public static async Task<SignatureAck> GetSignature(string hostVersion, string sn, string ssid)
        {
            JsonObject jo = new JsonObject();
            jo.SetNamedValue("serial_number", JsonValue.CreateStringValue(sn));
            jo.SetNamedValue("ssid", JsonValue.CreateStringValue(ssid));
            
            var response = await HttpRequest.Post(hostVersion + "/serial_number/encode", jo.ToString());
            HpApIResponse?.Invoke(response);
            var ack = new SignatureAck();
            var ret = DoValidation(response);
            if (ret.Code == 201)
            {
                JsonObject jsonObject = JsonObject.Parse(response);
                Signature signature = new Signature()
                {
                    AppId = jsonObject.GetNamedString("app_id", ""),
                    Guid = jsonObject.GetNamedString("hash", ""),
                    KeyVersion = (int)jsonObject.GetNamedNumber("key_version", 1),
                    ProductId = jsonObject.GetNamedString("pid", "1210"),
                    Sign = jsonObject.GetNamedString("sign", "")
                };

                var tokenObject = jsonObject.GetNamedObject("token");
                Token token = new Token()
                {
                    Value = tokenObject.GetNamedString("access_token", ""),
                    Type = tokenObject.GetNamedString("token_type", ""),
                    ExpireIn = (int)tokenObject.GetNamedNumber("expires_in", 0)
                };

                List<SkillInfo> skills = new List<SkillInfo>();
                var skillArray = jsonObject.GetNamedArray("skill_infos",new JsonArray());
                foreach (var item in skillArray)
                {
                    var skillObject = item.GetObject();
                    SkillInfo skillInfo = new SkillInfo
                    {
                        Icon= skillObject.GetNamedString("Icon", ""),
                        Introduction = skillObject.GetNamedString("Introduction", ""),
                        Name = skillObject.GetNamedString("Name", ""),
                        Usage = skillObject.GetNamedString("Usage", "")
                    };
                    skills.Add(skillInfo);
                }
                ack.Sign = signature;
                ack.Token = token;
                ack.SkillInfos = skills;
                ack.WakeupType = (PlatformWakeupType)jsonObject.GetNamedNumber("wakeup_type", 0);
                ack.Telphone = jsonObject.GetNamedString("service_telephone", "");
                ack.MobileTelphone = jsonObject.GetNamedString("service_mobilephone", "");
                ack.QrCodeUrl = jsonObject.GetNamedString("hp_service_qrcode", "");
            }

            ack.Error = ret;
            return ack;
        }

        public static async Task<string> GetDriverList(string hostVersion, string token, string tokeType, string pn, string driverName)
        {
            var parameters = new ValueSet();
            pn = string.IsNullOrEmpty(pn) ? "1":pn;
            if (string.IsNullOrEmpty(driverName))
            {
                parameters = new ValueSet()
                {
                    { "pn", pn}
                };
            }
            else
            {
                parameters = new ValueSet()
                {
                    { "pn", pn},
                    {"driverName",driverName }
                };
            }
            var response = await HttpRequest.GetAsync(hostVersion + "/driverlist", tokeType, token, parameters);
            return response;
        }

        public static async Task<string> GetObligationMessage(string hostVersion, string token, string tokeType, string pn, string sn)
        {
            var parameters = new ValueSet()
            {
                { "pn", pn },
                { "sn", sn }
            };
            var response = await HttpRequest.GetAsync(hostVersion + "/getDeviceServiceObligationMessage", tokeType, token, parameters);
            return response;
        }
        public static async Task<string> GetMaintainPosition(string hostVersion, string token, string tokeType, double latitude, double longitude)
        {
            var parameters = new ValueSet()
            {
                { "latitude", latitude},
                {"longitude",longitude }
            };
            var response = await HttpRequest.GetAsync(hostVersion + "/getDeviceMaintainPosition", tokeType, token, parameters);
            return response;
        }


        public static async Task<VersionAck> CheckVersion(string hostVersion, string token, string tokeType, string version)
        {
            //PackageVersion packageVersion = Package.Current.Id.Version;
            //string version = $"{packageVersion.Major}.{packageVersion.Minor}.{packageVersion.Build}.{packageVersion.Revision}";
            var parameters = new ValueSet()
            {
                { "version", version}
            };

            var response = await HttpRequest.GetAsync(hostVersion + "/version/validate", tokeType, token, parameters);

            var ret = DoValidation(response);
            if(ret.Code == 201)
            {
                JsonObject jsonObject = JsonObject.Parse(response);
                return new VersionAck()
                {
                    Force = jsonObject.GetNamedBoolean("force", false),
                    Latest = jsonObject.GetNamedString("latest", "0.0.0.0")
                };
            }
            else
            {
                return null;
            }
        }

        public static async Task<bool> DownloadRecord(int appId, string customerId, string deviceName, string hostVersion, string token, string tokeType)
        {
            JsonObject jo = new JsonObject();
            jo.SetNamedValue("app_id", JsonValue.CreateNumberValue(appId));
            jo.SetNamedValue("customer_id", JsonValue.CreateStringValue(customerId));
            jo.SetNamedValue("device_name", JsonValue.CreateStringValue(deviceName));
            var response = await HttpRequest.PostAsync(hostVersion + "/download/record", tokeType, token, jo.ToString());
            var ret = DoValidation(response);
            return ret.Code == 201 ? true : false;
        }

        public static async Task<bool> LoginRecord(string customerId, string deviceName, string hostVersion, string token, string tokeType)
        {
            JsonObject jo = new JsonObject();
            jo.SetNamedValue("customer_id", JsonValue.CreateStringValue(customerId));
            jo.SetNamedValue("device_name", JsonValue.CreateStringValue(deviceName));
            var response = await HttpRequest.PostAsync(hostVersion + "/login/record", tokeType, token, jo.ToString());

            var ret = DoValidation(response);
            return ret.Code == 201 ? true : false;
        }

        public static async Task<bool> Feedback(string customerId, string serialNumber, string appVersion, string email, string comments, string hostVersion, string token, string tokeType)
        {
            JsonObject jo = new JsonObject();
            jo.SetNamedValue("customer_id", JsonValue.CreateStringValue(customerId));
            jo.SetNamedValue("serial_number", JsonValue.CreateStringValue(serialNumber));
            jo.SetNamedValue("app_version", JsonValue.CreateStringValue(appVersion));
            jo.SetNamedValue("email", JsonValue.CreateStringValue(email));
            jo.SetNamedValue("comments", JsonValue.CreateStringValue(comments));
            var response = await HttpRequest.PostAsync(hostVersion + "/feedback/record", tokeType, token, jo.ToString());

            var ret = DoValidation(response);
            return ret.Code == 201 ? true : false;
        }

        public static async Task<bool> DauRecord(string customerId, string serialNumber, string hostVersion, string token, string tokeType)
        {
            JsonObject jo = new JsonObject();
            jo.SetNamedValue("customer_id", JsonValue.CreateStringValue(customerId));
            jo.SetNamedValue("serial_number", JsonValue.CreateStringValue(serialNumber));
            var response = await HttpRequest.PostAsync(hostVersion + "/dau/record", tokeType, token, jo.ToString());

            var ret = DoValidation(response);
            return ret.Code == 201 ? true : false;
        }

        public static async Task<AsrInfo> GetAsrPidAndKeyAsync(string hostVersion)
        {
            var response = await HttpRequest.GetAsync(hostVersion + "/asr", null, null, null);

            try
            {
                var info = new AsrInfo();
                JsonObject jsonObject = JsonObject.Parse(response);

                info.Pid = (int)jsonObject.GetNamedNumber("pid", 0);
                info.SecretKey = jsonObject.GetNamedString("secret_key", "");

                return info;
            }
            catch(Exception)
            {
                return null;
            }
        }

        public static async Task<Dictionary<string,string>> GetAPPs(string hostVersion, string token, string tokeType)
        {

            var response = await HttpRequest.GetAsync(hostVersion + "/openapps", tokeType, token, null);
            try
            {
                Dictionary<string, string> ret = new Dictionary<string, string>();
                foreach (var item in JsonArray.Parse(response))
                {
                    var jo=item.GetObject();
                    if (ret.ContainsKey(jo["app_name"].GetString())) continue;
                    ret.Add(jo["app_name"].GetString(),jo["app_id"].GetString());
                }
                return ret;
            }
            catch
            {
                return new Dictionary<string, string>();
            }
        }

        private static Error DoValidation(string response)
        {
            Error error = new Error();
            try
            {
                JsonObject jsonObject = JsonObject.Parse(response);
                error.Code = (int)jsonObject.GetNamedNumber("code", 201);
                error.Message = jsonObject.GetNamedString("message", "");
            }
            catch (Exception ex) 
            {
                error.Code = -1;
                error.Message = "Exception when parse response.";
            }

            return error;
        }
    }
}
